// 封装微信的 wx.request 方法 
class WxRequest {

  // 默认参数
  defaults = {
    baseUrl: '',
    url: '',
    data: null,
    method: 'GET',
    header: {
      "Content-type": "application/json"
    },
    isLoading: true,
    timeout: 60000
  }

  // 拦截器
  interceptors = {
    // 请求拦截器 对请求参数进行修改
    request: (config) => config,
    // 响应拦截器 对服务器响应的数据进行修改
    response: (response) => response,
  }

  // 数组队列 用于存储请求标识
  queue = []

  constructor(param = {}) {
    this.defaults = Object.assign({}, this.defaults, param);
  }

  // 接受一个对象类型的参数 接收值和 wx.request 需要的参数一致
  request(options) {
    // 判断上一次的定时器
    this.timerId && clearTimeout(this.timerId)

    options.url = this.defaults.baseUrl + options.url
    options = {
      ...this.defaults,
      ...options
    }
    // 在请求发送之前 添加 loading 效果
    if (options.isLoading && options.method !== 'upload') {
      this.queue.length === 0 && wx.showLoading({
        title: '加载中'
      })
      // 往队列里添加请求标识 每发送一次请求添加一次自定义标识
      this.queue.push('request')
    }

    // 在请求发送之前 调用请求拦截器
    options = this.interceptors.request(options)

    return new Promise((resolve, reject) => {
      if (options.method === 'upload') {
        wx.uploadFile({
          ...options,
          success: (res) => {
            res.data = JSON.parse(res.data)
            const mergeRes = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })
            resolve(this.interceptors.response(mergeRes))
          },
          fail: (err) => {
            const mergeErr = Object.assign({}, err, {
              config: options,
              isSuccess: false
            })
            reject(this.interceptors.response(mergeErr))
          }
        })
      } else {
        wx.request({
          ...options,
          success: (res) => {
            const mergeRes = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })
            resolve(this.interceptors.response(mergeRes))
          },
          fail: (err) => {
            const mergeErr = Object.assign({}, err, {
              config: options,
              isSuccess: false
            })
            reject(this.interceptors.response(mergeErr))
          },
          complete: () => {
            if (options.isLoading && options.method !== 'upload') {
              // 不管请求成功还是失败 都需要隐藏 loading
              this.queue.pop()
              // 等队列里面没有标识了 表示所有的请求都结束了
              // 再往队列里放一个标识 用于解决两次请求过快 loading 闪烁问题
              this.queue.length === 0 && this.queue.push('request')
              // 重启一个线程
              this.timerId = setTimeout(() => {
                this.queue.pop()
                this.queue.length === 0 && wx.hideLoading()
                clearTimeout(this.timerId)
              }, 1);
            }
          }
        })
      }
    })
  }

  get(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'GET'
    }, config))
  }

  delete(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'DELETE'
    }, config))
  }

  post(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'POST'
    }, config))
  }

  put(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'PUT'
    }, config))
  }

  // 通过展开运算符接收传递的参数 会被转换成数组
  all(...promise) {
    return Promise.all(promise)
  }

  // 将图片上传到服务器
  upload(url, filePath, name = "file", config = {}) {
    return this.request(
      Object.assign({
        url,
        filePath,
        name,
        method: "upload"
      }, config)
    );
  }
}

export default WxRequest